home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / telecom / 96 / c / fsel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-01-15  |  32.6 KB  |  838 lines

  1. /*
  2.  * a new FSEL placed in public domain by D N Korte 26 Dec 86.
  3.  * Do with it whatever you want...
  4.  * (set TABSIZE = 4)
  5.  */
  6. #include <obdefs.h>
  7. #include <gemdefs.h>
  8. #include <gembind.h>
  9. #include <osbind.h>
  10.  
  11. #define TRUE  1
  12. #define FALSE 0
  13.  
  14. #define QUIT     0
  15. #define CONTINUE 1
  16.  
  17. #define MAXFILES 144      /* abs max 327 (overflow FS_calc_curfirst) */
  18. #define WINDSIZE   9      /* size of file window */
  19. #define DIAMOND_THINGY 7
  20.  
  21. #define CANCBUT 2
  22. #define OKBUT   3
  23. #define NEWNAME 4
  24. #define WINDOW  5
  25. #define DRVA    6
  26. #define DRVB    7
  27. #define DRVC    8
  28. #define DRVD    9
  29. #define DRVE   10
  30. #define DRVF   11
  31. #define SLEXTN0 12
  32. #define SLEXTN1 13
  33. #define SLEXTN2 14
  34. #define SLEXTN3 15
  35. #define SLEXTN4 16
  36. #define EXTN3   17
  37. #define EXTN4   18
  38. #define FNAM1   19
  39. #define FNAM2   20
  40. #define FNAM3   21
  41. #define FNAM4   22
  42. #define FNAM5   23
  43. #define FNAM6   24
  44. #define FNAM7   25
  45. #define FNAM8   26
  46. #define FNAM9   27
  47. #define FILEBOX 28
  48. #define TOPBAR  29
  49. #define UPARROW 30
  50. #define SLIDBOX 31
  51. #define MVSLIDE 32
  52. #define DNARROW 33
  53. #define TOPTEXT 34
  54.  
  55. struct finfo {
  56.     char name[9];    /* name of file */
  57.     char extn[4];    /* extension of it */
  58.     int  dirflag;    /* FALSE if not a directory, TRUE if is directory */
  59. } ;
  60.  
  61. char *rs_strings[] = {
  62.     "",                 /* 0 */
  63.     "CANCEL",           /* 1 */
  64.     "OK",               /* 2 */
  65.     "___________",        /* 3 initial pe_text for 'newname' */
  66.     "A:",               /* 4 */
  67.     "B:",               /* 5 */
  68.     "C:",               /* 6 */
  69.     "D:",               /* 7 */
  70.     "E:",               /* 8 */
  71.     "F:",               /* 9 */
  72.     "________.___",        /* 10 template for newname */
  73.     ".___",             /* 11 template for extensions */
  74.     "                ", /* 12 for file name slots in menu box*/
  75.     "FFFFFFFFFFF",      /* 13 validation for newname */
  76.     "FFF"               /* 14 validation for extensions */               
  77. };
  78.  
  79. char file_ids[WINDSIZE][17]; /* spot for (10) 16-char formatted filenames in menu */
  80.  
  81. TEDINFO rs_tedinfo[] = {
  82.     0L,rs_strings[10],rs_strings[13],3,0,0,0x1180,0, 0,0,13, /* 0 for newname */
  83.     0L,rs_strings[11],rs_strings[ 0],3,0,2,0x1180,0,-2,0,5,  /* 1 for extn0   */
  84.     0L,rs_strings[11],rs_strings[ 0],3,0,2,0x1180,0,-2,0,5,  /* 2 for extn1   */
  85.     0L,rs_strings[11],rs_strings[ 0],3,0,2,0x1180,0,-2,0,5,  /* 3 for extn2   */
  86.     0L,rs_strings[11],rs_strings[14],3,0,2,0x1180,0,-2,0,5,  /* 4 for extn3   */
  87.     0L,rs_strings[11],rs_strings[14],3,0,2,0x1180,0,-2,0,5,  /* 5 for extn4   */
  88.     0L, rs_strings[0],rs_strings[ 0],3,0,2,0x1180,0, 0,0,0   /* 6 for pathname in TOPBAR */
  89. };
  90. /*  ^      ^               ^         ^ ^ ^   ^    ^  ^ ^ ^
  91.     |      |               |         | | |   |    |  | | +-- te_tmplen length of template (+1 for null)
  92.     |      |               |         | | |   |    |  | ----- te_txtlen length of text     (+1 for null)
  93.     |      |               |         | | |   |    |  +------ te_thickness  border thickness (-) outside
  94.     |      |               |         | | |   |    +--------- te_junk2
  95.     |      |               |         | | |   +-------------- te_color packed color information 
  96.     |      |               |         | | +------------------ te_just 0=left 1=right 2=centered
  97.     |      |               |         | +-------------------- te_junk1
  98.     |      |               |         +---------------------- te_font 3=system 5=small
  99.     |      |               +------------------------------- *te_pvalid ptr to validation chars
  100.     |      +----------------------------------------------- *te_ptmplt ptr to template
  101.     +------------------------------------------------------ *te_ptext  ptr to text
  102. */
  103.  
  104. OBJECT rs_object[] = {
  105.     -1,1,34,G_BOX,      NONE,                        OUTLINED,    0x21100L, 0, 0,38,15, /* 0 dialog box */
  106.     2,-1,-1,G_STRING,   NONE,                        NORMAL,            0L, 2, 1,34,1,  /* 1 TITLE */
  107.     3,-1,-1,G_BUTTON,   SELECTABLE|EXIT,             NORMAL, rs_strings[1],22, 3, 6,1,  /* 2 CANCBUT */
  108.     4,-1,-1,G_BUTTON,   SELECTABLE|EXIT|DEFAULT,     NORMAL, rs_strings[2],30, 3, 6,1,  /* 3 OKBUT */
  109.     5,-1,-1,G_FTEXT,    EDITABLE,                    NORMAL,&rs_tedinfo[0],22, 5,12,1,  /* 4 NEWNAME */
  110.     6,-1,-1,G_IBOX,     NONE,                        NORMAL,     0xFF1100L, 2, 3,18,11, /* 5 WINDOW (outline of pretend window) */
  111.     7,-1,-1,G_BUTTON,   SELECTABLE|EXIT|RBUTTON,     NORMAL, rs_strings[4],22, 7, 4,1,  /* 6 DRVA */
  112.     8,-1,-1,G_BUTTON,   SELECTABLE|EXIT|RBUTTON,     NORMAL, rs_strings[5],27, 7, 4,1,  /* 7 DRVB */
  113.     9,-1,-1,G_BUTTON,   SELECTABLE|EXIT|RBUTTON,     NORMAL, rs_strings[6],32, 7, 4,1,  /* 8 DRVC */
  114.     10,-1,-1,G_BUTTON,  SELECTABLE|EXIT|RBUTTON,     NORMAL, rs_strings[7],22, 9, 4,1,  /* 9 DRVD */
  115.     11,-1,-1,G_BUTTON,  SELECTABLE|EXIT|RBUTTON,     NORMAL, rs_strings[8],27, 9, 4,1,  /* 10 DRVE */
  116.     12,-1,-1,G_BUTTON,  SELECTABLE|EXIT|RBUTTON,     NORMAL, rs_strings[9],32, 9, 4,1,  /* 11 DRVF */
  117.     13,-1,-1,G_FBOXTEXT,SELECTABLE|TOUCHEXIT,        NORMAL,&rs_tedinfo[1],22,11, 4,1,  /* 12 SLEXTN0 */
  118.     14,-1,-1,G_FBOXTEXT,SELECTABLE|TOUCHEXIT,        NORMAL,&rs_tedinfo[2],27,11, 4,1,  /* 13 SLEXTN1 */
  119.     15,-1,-1,G_FBOXTEXT,SELECTABLE|TOUCHEXIT,        NORMAL,&rs_tedinfo[3],32,11, 4,1,  /* 14 SLEXTN2 */
  120.     16,-1,-1,G_BOX,     SELECTABLE|TOUCHEXIT,        NORMAL,     0xFE1100L,22,13, 2,1,  /* 15 SLEXTN3 */
  121.     17,-1,-1,G_BOX,     SELECTABLE|TOUCHEXIT,        NORMAL,     0xFE1100L,30,13, 2,1,  /* 16 SLEXTN4 */
  122.     18,-1,-1,G_FBOXTEXT,EDITABLE,                    NORMAL,&rs_tedinfo[4],24,13, 4,1,  /* 17 EXTN3 */
  123.     28,-1,-1,G_FBOXTEXT,EDITABLE,                    NORMAL,&rs_tedinfo[5],32,13, 4,1,  /* 18 EXTN4 */
  124.     20,-1,-1,G_STRING,  SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,&file_ids[0][0], 0, 0,15,1,  /* 19 FNAM1 (note that for doubleclick */
  125.     21,-1,-1,G_STRING,  SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,&file_ids[1][0], 0, 1,15,1,  /* 20 FNAM2 (to work, these objects must */
  126.     22,-1,-1,G_STRING,  SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,&file_ids[2][0], 0, 2,15,1,  /* 21 FNAM3 (be G_STRING and must have */
  127.     23,-1,-1,G_STRING,  SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,&file_ids[3][0], 0, 3,15,1,  /* 22 FNAM4 (ob_flags exactly as shown. */
  128.     24,-1,-1,G_STRING,  SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,&file_ids[4][0], 0, 4,15,1,  /* 23 FNAM5 (When selected, bit 15 of */
  129.     25,-1,-1,G_STRING,  SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,&file_ids[5][0], 0, 5,15,1,  /* 24 FNAM6 (form_do return will be */
  130.     26,-1,-1,G_STRING,  SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,&file_ids[6][0], 0, 6,15,1,  /* 25 FNAM7 (set if gotten by a */
  131.     27,-1,-1,G_STRING,  SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,&file_ids[7][0], 0, 7,15,1,  /* 26 FNAM8 (doubleclick. */
  132.     28,-1,-1,G_STRING,  SELECTABLE|TOUCHEXIT|RBUTTON,NORMAL,&file_ids[8][0], 0, 8,15,1,  /* 27 FNAM9 */
  133.     29,19,27,G_BOX,     NONE,                        NORMAL,      0x011100L, 2, 4,15,10, /* 28 FILEBOX (box is parent for FNAMs) */
  134.     30,-1,-1,G_BOX,     NONE,                        NORMAL,      0xFF1121L, 2, 3,18,1,  /* 29 TOPBAR */
  135.     31,-1,-1,G_BOXCHAR, TOUCHEXIT,                   NORMAL,    0x01011180L,17, 4, 3,1,  /* 30 UPARROW (adjust y later) */
  136.     33,32,32,G_BOX,     TOUCHEXIT,                   NORMAL,      0x011111L,17, 5, 3,7,  /* 31 SLIDBOX (adjust y later) */
  137.     31,-1,-1,G_BOX,     TOUCHEXIT,                   NORMAL,      0x011100L, 0, 0, 3,1,  /* 32 MVSLIDE */                          
  138.     34,-1,-1,G_BOXCHAR, TOUCHEXIT,                   NORMAL,    0x02011100L,17,12, 3,1,  /* 33 DNARROW (adjust y and h later) */
  139.      0,-1,-1,G_TEXT,    LASTOB,                      NORMAL, &rs_tedinfo[6], 3, 3,16,1   /* 34 TOPTEXT */
  140. };
  141. /*   ^  ^ ^    ^           ^                            ^        ^           ^  ^  ^ ^ 
  142.      |  | |    |           |                            |        |           |  |  | +-- ob_height height of obj (now chars, but
  143.      |  | |    |           |                            |        |           |  |  +---- ob_width  width  of obj (must cnvt to pixels
  144.      |  | |    |           |                            |        |           |  +------- ob_y      y coord relative to parent 
  145.      |  | |    |           |                            |        |           +---------- ob_x      x coord relative to parent 
  146.      |  | |    |           |                            |        +---------------------  ob_spec   obj determines meaning (p11-55,60)
  147.      |  | |    |           |                            +------------------------------  ob_state  current state of obj (p.11-61 MM)
  148.      |  | |    |           +-----------------------------------------------------------  ob_flags  attributes for obj (p.11-60 MM)
  149.      |  | |    +-----------------------------------------------------------------------  ob_type   object type (p. 11-59 MM)
  150.      |  | +----------------------------------------------------------------------------  ob_tail   ptr to last child of obj or -1
  151.      |  +------------------------------------------------------------------------------  ob_head   ptr to first child of obj or -1
  152.      +---------------------------------------------------------------------------------  ob_next   ptr to next sibling or -1        
  153.  
  154. */
  155.  
  156. int xdial,ydial,wdial,hdial,        /* co-ord for dialog box */
  157.     xwind,ywind,wwind,hwind;        /* file selector window outside borders */
  158.                        
  159. int firstcall = TRUE;                /* for first-run initialization */
  160.  
  161. /*
  162.  * 
  163.  * Function fsel ()                                                   
  164.  * This is what we're here for !!!
  165.  * Can't say much more 'cuz MM editor is almost full of characters.
  166.  * 
  167.  */
  168. fsel(title,path,driv,sextn,extn0,extn1,extn2,extn3,extn4,fullname)
  169.  
  170. char *path,                /* IO initial path spec \ ... \ no drive; returns selected path */
  171.      *fullname,            /* O  returns complete path and file */
  172.      *title,             /* I  display title for box */
  173.      *extn0,*extn1,     /* I  extension text not including "." for each of 1st 3 extn boxes  */
  174.      *extn2,             /*    NOTE for all 5 boxes this should be 3 chars long, even if spaces   */
  175.      *extn3,*extn4;     /* IO extension text for last 2 extn boxes (editable) */
  176.  
  177.  
  178. int     *driv,                /* IO selects drive -1=default 0=A: .. 5=F: */
  179.      *sextn;            /* IO bitmap selected extn boxes :
  180.                              0x0001 = extn0    0x0002 = extn1    0x0004 = extn2
  181.                             0x0008 = extn3    0x0010 = extn4
  182.                         */
  183. {
  184.  
  185. struct finfo files[MAXFILES];           /* holds name, extn, dir for all files */
  186.  
  187. char newname[12],                       /* holds user-typed name */
  188.      fnam[13],                           /* will build return filename here */
  189.      c,
  190.      drivs[3],                           /* current dir as string i.e. "B:" */
  191.      dispath[17];                       /* displayable pathname (trunc to 16 chars max) */
  192.  
  193. int  i,fp,ret,x,y,w,h;
  194. int  action,                           /* flag */
  195.      button,                           /* button code from dialog box */
  196.      slidpsn,                          /* slider position 0-1000 */
  197.      goodfiles[MAXFILES],               /* has indices into 'files[]' of files matching extn specifications */
  198.      numfiles,                         /* total number of files in 'files[]' */
  199.      numgood,                           /* number of files noted in 'goodfiles[]' */
  200.      curfirst,                           /* index into 'goodfiles[]' of first displayable file */
  201.      hchar,                               /* height of character in pixels */
  202.      my,                               /* mouse position y coordinate */
  203.      doubleclick,                       /* TRUE if double-clicked on item, else FALSE */
  204.      editfield;                           /* index of field to edit */
  205.  
  206. TEDINFO *p;
  207.  
  208.     /*
  209.      * On the very first call to this subroutine we must do some 
  210.      * setup stuff...  Primarily adjustments to the resource table
  211.      * to adjust for screen resolution, and to adjust element locations
  212.      * which do not live on even character boundaries.
  213.      */
  214.     if (firstcall) {
  215.         firstcall = FALSE;
  216.     
  217.         for(i=0; i<=34; i++) 
  218.             rsrc_obfix(rs_object,i);        /* chg coord from char to pixel */
  219.                         
  220.         /*
  221.          * also adjust size of SLIDBOX and xxARROWs into half-char sizes
  222.          * because 1 char tall is too short to allow boxchar to display the arrows,
  223.          * but 2 chars tall looks silly.
  224.          */
  225.         i=graf_handle(&ret,&hchar,&ret,&ret);
  226.         rs_object[UPARROW].ob_height += hchar/2;
  227.         rs_object[DNARROW].ob_y      += hchar/2;
  228.         rs_object[DNARROW].ob_height += hchar/2;
  229.         rs_object[SLIDBOX].ob_y      += hchar/2;
  230.  
  231.         /*
  232.          * and similarly, adjust position of filenames in menu box
  233.          * so that 9 fit nicely into a box that tightly fits 10
  234.          */
  235.          for (i=0; i<WINDSIZE; i++)
  236.              rs_object[FNAM1+i].ob_y += hchar/2;
  237.     }
  238.  
  239.     rs_tedinfo[0].te_ptext = &newname;  
  240.     rs_tedinfo[1].te_ptext = extn0 ;
  241.     rs_tedinfo[2].te_ptext = extn1 ;
  242.     rs_tedinfo[3].te_ptext = extn2 ;
  243.     rs_tedinfo[4].te_ptext = extn3 ;
  244.     rs_tedinfo[5].te_ptext = extn4 ;
  245.     rs_tedinfo[6].te_ptext = dispath  ;
  246.  
  247.  
  248.     for (i=0; i<=6; i++) {
  249.         rs_tedinfo[i].te_txtlen = strlen(rs_tedinfo[i].te_ptext) + 1 ;
  250.     }
  251.     
  252.     rs_object[1].ob_spec  = title;
  253.     strcpy(newname,rs_strings[3]);
  254.     FS_pathtrunc(dispath,path);
  255.     for (i=0; i<WINDSIZE; i++) strcpy(&file_ids[i][0],rs_strings[12]);
  256.     editfield = NEWNAME;
  257.     
  258.     /*
  259.      * If user passed blanks for editable extensions, this is good
  260.      * but it will look funny -- put in initial underscores instead,
  261.      * also if he just passed unitialized (empty) string do it too.
  262.      * We must assume that string will be long enough...
  263.      */
  264.     if((extn3[0] == ' ')||(strlen(extn3) == 0)) strcpy(extn3,"___");
  265.     if((extn4[0] == ' ')||(strlen(extn4) == 0)) strcpy(extn4,"___");
  266.     
  267.  
  268.  
  269.     if (*sextn & 0x0001) rs_object[SLEXTN0].ob_state |= SELECTED;
  270.     if (*sextn & 0x0002) rs_object[SLEXTN1].ob_state |= SELECTED;
  271.     if (*sextn & 0x0004) rs_object[SLEXTN2].ob_state |= SELECTED;
  272.     if (*sextn & 0x0008) rs_object[SLEXTN3].ob_state |= SELECTED;
  273.     if (*sextn & 0x0010) rs_object[SLEXTN4].ob_state |= SELECTED;
  274.  
  275.  
  276.  
  277.     if (*driv  == -1)     *driv = Dgetdrv();            /* get cur logged drive if needed */    
  278.     rs_object[(*driv)+DRVA].ob_state |= SELECTED;
  279.     drivs[0] = (*driv) +'A' ;    drivs[1] = ':' ;   drivs[2] = '\0' ;
  280.  
  281.     form_center (&rs_object,&xdial,&ydial,&wdial,&hdial);
  282.     x=y=w=h=0;
  283.     form_dial (0,x,y,w,h,xdial,ydial,wdial,hdial);      /* reserve room */
  284.     form_dial (1,x,y,w,h,xdial,ydial,wdial,hdial);      /* grow box */
  285.     objc_draw (&rs_object,0,2,xdial,ydial,wdial,hdial); /* draw the dialog box */
  286.     FS_dir_read(drivs,path,files,&numfiles,dispath);
  287.     FS_dir_select_good(*sextn,extn0,extn1,extn2,extn3,extn4,
  288.                     files,numfiles,goodfiles,&numgood,&curfirst);
  289.     FS_calc_slid_box(numgood,curfirst,FALSE);             /* calculate initial slider position */
  290.  
  291.     FS_dir_dis(files,goodfiles,numgood,curfirst);
  292.  
  293.     action = CONTINUE;                                       /* look for new button press */
  294.     while (action == CONTINUE) {                           /* loop while operator plays */
  295.  
  296.         if (rs_object[SLEXTN3].ob_state & SELECTED)     /* setup status of (SL)EXTN3 click-ability */
  297.             rs_object[EXTN3].ob_flags = TOUCHEXIT;
  298.         else
  299.             rs_object[EXTN3].ob_flags = EDITABLE;
  300.  
  301.         if (rs_object[SLEXTN4].ob_state & SELECTED)     /* setup status of (SL)EXTN4 click-ability */
  302.             rs_object[EXTN4].ob_flags = TOUCHEXIT;
  303.         else
  304.             rs_object[EXTN4].ob_flags = EDITABLE;
  305.  
  306.         button = form_do(&rs_object,editfield);            /* manage user's actions until a button press */    
  307.         if (button & 0x8000) {                            /* if double-click ... */
  308.             doubleclick  = TRUE;
  309.             button      &= ~0x8000;                        /* (remove double-click bit from botton code) */
  310.         }
  311.         else
  312.             doubleclick  = FALSE;
  313.             
  314.         switch (button) {                                /* now prepare to act upon user's request */
  315.             case CANCBUT: action = QUIT; rs_object[CANCBUT].ob_state &= ~SELECTED; break;
  316.             case OKBUT:   action = QUIT; rs_object[OKBUT].ob_state   &= ~SELECTED; break;
  317.  
  318.             case DRVA:
  319.             case DRVB:
  320.             case DRVC:
  321.             case DRVD:
  322.             case DRVE:
  323.             case DRVF:       *driv = button - DRVA; 
  324.                           drivs[0] = (*driv) + 'A'; drivs[1] = ':';  drivs[2] = '\0';
  325.                           strcpy(path,"\\");
  326.                           FS_pathtrunc(dispath,path);
  327.                           FS_dir_read(drivs,path,files,&numfiles,dispath);
  328.                           FS_dir_select_good(*sextn,extn0,extn1,extn2,extn3,extn4,
  329.                                 files,numfiles,goodfiles,&numgood,&curfirst);
  330.                           FS_dir_dis(files,goodfiles,numgood,curfirst);
  331.                           FS_setname(-1,newname);
  332.                           break;
  333.  
  334.             case SLEXTN0:
  335.             case SLEXTN1:
  336.             case SLEXTN2:
  337.             case SLEXTN3:
  338.             case SLEXTN4: i = 0x01 << (button - SLEXTN0);
  339.                           *sextn ^= i ; 
  340.                           FS_dir_select_good(*sextn,extn0,extn1,extn2,extn3,extn4,
  341.                                 files,numfiles,goodfiles,&numgood,&curfirst);
  342.                           FS_dir_dis(files,goodfiles,numgood,curfirst);
  343.                           FS_setname(-1,newname);
  344.                           break;
  345.  
  346.             case FNAM1:
  347.             case FNAM2:
  348.             case FNAM3:
  349.             case FNAM4:
  350.             case FNAM5:
  351.             case FNAM6:
  352.             case FNAM7:
  353.             case FNAM8:
  354.             case FNAM9: i = button - FNAM1;
  355.                         fp= goodfiles[curfirst+i] ;                            /* (fp points into files[]) */
  356.                         if (files[fp].dirflag) {                            /* if a directory of any flavor */
  357.                             if (strcmp(files[fp].name,".") == 0)             /* current directory */
  358.                                   /* do nothing special */ ;
  359.                               else if (strcmp(files[fp].name,"..") == 0) {    /* parent directory */
  360.                                   FS_path_shorten(path,dispath);
  361.                                   FS_dir_read(drivs,path,files,&numfiles,dispath);
  362.                                   FS_dir_select_good(*sextn,extn0,extn1,extn2,extn3,extn4,
  363.                                     files,numfiles,goodfiles,&numgood,&curfirst);
  364.                             }
  365.                             else {                                            /* another directory */
  366.                                 FS_path_lengthen(path,fp,files,dispath);
  367.                                 FS_dir_read(drivs,path,files,&numfiles,dispath);
  368.                                   FS_dir_select_good(*sextn,extn0,extn1,extn2,extn3,extn4,
  369.                                     files,numfiles,goodfiles,&numgood,&curfirst);
  370.                               }
  371.                               FS_dir_dis(files,goodfiles,numgood,curfirst);    /* then always display the selected directory */
  372.                               FS_setname(-1,newname);
  373.                           }                                                    /* end of 'if a directory' stuff */
  374.                           else {                                            /* here it must be just a file */
  375.                              FS_setname(i,newname);
  376.                              if (doubleclick) {                                /* a doubleclick causes default OKBUT too */
  377.                                  action   = QUIT;
  378.                                  button   = OKBUT;
  379.                              }
  380.                           }
  381.                           break;
  382.             case MVSLIDE: if (rs_object[SLIDBOX].ob_height==rs_object[MVSLIDE].ob_height) break;     /* do nothing if full size */
  383.                           slidpsn = graf_slidebox(&rs_object,SLIDBOX,MVSLIDE,1);
  384.                           FS_calc_curfirst(slidpsn,numgood,&curfirst);
  385.                           FS_calc_slid_box(numgood,curfirst,TRUE);
  386.                           FS_dir_dis(files,goodfiles,numgood,curfirst);
  387.                           FS_setname(-1,newname);
  388.                           break;
  389.             case SLIDBOX: graf_mkstate(&ret,&my,&ret,&ret);
  390.                           if (my > (ydial+rs_object[SLIDBOX].ob_y+rs_object[MVSLIDE].ob_y)) 
  391.                              FS_shift_curfirst(WINDSIZE,numgood,&curfirst);
  392.                           else
  393.                                FS_shift_curfirst(-WINDSIZE,numgood,&curfirst);
  394.                           FS_calc_slid_box(numgood,curfirst,TRUE);
  395.                           FS_dir_dis(files,goodfiles,numgood,curfirst);
  396.                           FS_setname(-1,newname);
  397.                           break;
  398.             case UPARROW: FS_shift_curfirst(-1,numgood,&curfirst);
  399.                           FS_calc_slid_box(numgood,curfirst,TRUE);
  400.                           FS_dir_dis(files,goodfiles,numgood,curfirst);
  401.                           FS_setname(-1,newname);
  402.                           break;
  403.             case DNARROW: FS_shift_curfirst(1,numgood,&curfirst);
  404.                           FS_calc_slid_box(numgood,curfirst,TRUE);
  405.                           FS_dir_dis(files,goodfiles,numgood,curfirst);
  406.                           FS_setname(-1,newname);
  407.                           break;
  408.                           
  409.                           /*
  410.                            * to get to EXTN3 then EXTN3 must have been TOUCHEXIT
  411.                            * which means that SLEXTN3 must have been SELECTED.
  412.                            * When we touched on the EXTN3 field we signify that we
  413.                            * want to edit it -- therefore we unSELECT the box so
  414.                            * that we can force a directory read when it next gets selected.
  415.                            */
  416.             case EXTN3:      rs_object[EXTN3].ob_flags = EDITABLE;
  417.                           objc_change(&rs_object,SLEXTN3,0,xdial,ydial,wdial,hdial,NORMAL,1);
  418.                           *sextn &= ~0x0008;
  419.                           editfield = EXTN3;
  420.                           break;
  421.                           
  422.                           /* similar logic here... */
  423.             case EXTN4:      rs_object[EXTN4].ob_flags = EDITABLE;
  424.                           objc_change(&rs_object,SLEXTN4,0,xdial,ydial,wdial,hdial,NORMAL,1);
  425.                           *sextn &= ~0x0010;
  426.                           editfield = EXTN4;
  427.                           break;              
  428.         }    /* end of switch(button)    */
  429.     }        /* end of while(action) */
  430.   
  431.     form_dial (2,x,y,w,h,xdial,ydial,wdial,hdial);  /* shrink dialog box */
  432.     form_dial (3,x,y,w,h,xdial,ydial,wdial,hdial);  /* release its room */
  433.     
  434.     for (i=0; i<8; i++) {                            /* build formatted filename from newname */
  435.         if ((c=newname[i]) == ' ') break ;            /* (scan name part until ends at space */
  436.         if ( c == '_' ) break;                        /* (also stops at _ in case no name was ever selected! */
  437.         fnam[i]   = c;
  438.         fnam[i+1] = '\0';
  439.     }
  440.     if((newname[8] != ' ')&&(newname[8] != '_')) {    /* (if there is an extension) */
  441.         fnam[i++] = '.';
  442.         fnam[i]   = '\0';
  443.         strcat(&fnam[i],&newname[8]);
  444.     }
  445.     
  446.     strcpy(fullname,drivs);                            /* finally, build a returnable name with full path info too */
  447.     strcat(fullname,path);
  448.     strcat(fullname,fnam);
  449.     
  450.     if (button == CANCBUT) return (0);                /* then return */
  451.     return(1);
  452. }
  453.  
  454. /* 
  455.  * function FS_shift_curfirst() is called when the slider
  456.  * is moved by an arrow key or a pageup/pagedn request.
  457.  * it returns a new value for curfirst (index into goodfiles)
  458.  */
  459. FS_shift_curfirst(inc,numgood,curfirst)
  460. int  inc,                    /* typically -1,1 (arrow), -9,+9 pagedn,pageup */
  461.      numgood,                /* total number of good files */
  462.      *curfirst;                /* returns new value for curfirst */
  463. {
  464.     *curfirst += inc;        /* change it as requested */
  465.                                 
  466.     /* then fix it if necessary */
  467.     if (*curfirst > (numgood-WINDSIZE)) *curfirst = numgood-WINDSIZE;
  468.     if (*curfirst < 0) *curfirst = 0;
  469. }
  470.  
  471. /*
  472.  * function FS_calc_curfirst() is called after
  473.  * a boxslide operation to find new value for curfirst.
  474.  */
  475. FS_calc_curfirst(slidpsn,numgood,curfirst)
  476. int slidpsn,        /* slider psn as returned from graf_slidbox 0-1000 */
  477.     numgood,        /* total number of good files */
  478.     *curfirst;        /* returned index into goodfiles */
  479. {
  480.     *curfirst = (numgood * (slidpsn/10)) / 100 ;   /* funny scaling to avoid arith overflow */
  481.     if (*curfirst > (numgood - WINDSIZE)) *curfirst = numgood - WINDSIZE;
  482. }
  483.  
  484. /*  
  485.  * function FS_calc_slid_box() is called to calculate
  486.  * new dimensions for the moving box, and draw it if necessary.
  487.  */
  488. FS_calc_slid_box(numgood,curfirst,drawit)
  489. int numgood,            /* number of good files */
  490.     curfirst,            /* index into goodfiles[] */
  491.     drawit;                /* FALSE = don't draw, TRUE = please draw */
  492. {
  493.     if (numgood <= WINDSIZE) {                    /* then sliding box is full size */
  494.         rs_object[MVSLIDE].ob_y      = 0;        /* position at top (rel to parent) */
  495.         rs_object[MVSLIDE].ob_height = rs_object[SLIDBOX].ob_height;
  496.     }
  497.     else {
  498.         rs_object[MVSLIDE].ob_height = (rs_object[SLIDBOX].ob_height * WINDSIZE) / numgood ;
  499.         rs_object[MVSLIDE].ob_y      = (rs_object[SLIDBOX].ob_height * curfirst) / numgood ;
  500.     }
  501.  
  502.     if (drawit) objc_draw(&rs_object,SLIDBOX,2,xdial,ydial,wdial,hdial);
  503.  
  504. /*
  505.  * function FS_setname() sets a filename or blanks into the NEWNAME field
  506.  * if i== -1 then blanks are set, otherwise file_ids[i] is set
  507.  */
  508. FS_setname(i,newname)
  509. int  i;
  510. char *newname;
  511. {
  512.     if (i == -1) 
  513.         strcpy(newname,rs_strings[3]);
  514.     else {
  515.         strncpy(newname,&file_ids[i][2],8);
  516.         strncpy(&newname[8],&file_ids[i][11],3);
  517.     }
  518.     objc_draw(&rs_object,NEWNAME,1,xdial,ydial,wdial,hdial);
  519. }
  520.     
  521.  
  522. /*
  523.  * function FS_dir_read() reads specified directory
  524.  * and stores names in 'files' array.  Also adjusts numfiles.
  525.  */
  526. FS_dir_read(drivs,path,files,numfiles,dispath)        /* function returns 0 on error 1 on success */
  527. char         *drivs,*path,*dispath;
  528. struct finfo files[];
  529. int          *numfiles;
  530.  
  531. {
  532. char fullname[14];                            /* full name of file from dta */
  533. int  dotat,error,i,numdirs,exch;
  534. char fullpath[80],                            /* full path spec with driv, pathlist, and *.*  */
  535.      *p,c;
  536.  
  537.     *numfiles = 0;                            /* no files found yet */
  538.     p = (char*)Fgetdta();
  539.  
  540.     do {
  541.         strcpy(fullpath,drivs);
  542.         strcat(fullpath,path);
  543.         strcat(fullpath,"*.*");
  544.         error = Fsfirst(fullpath,0x10);
  545.         if (error == -33) {
  546.             i = form_alert(2,"[1][You have specified either|an empty disk or a nonexistant path...][CONTINUE|RETRY|BACKUP PATH]");
  547.             switch(i) {
  548.                 case 1: return(1);            /* quit indicating success (?) */
  549.                 case 2: break;                /* just do it again */
  550.                 case 3: FS_path_shorten(path,dispath); 
  551.             }
  552.         }
  553.         else if (error != 0) {
  554.             i=form_error(error);
  555.             return(0);
  556.         }
  557.     } while (error == -33);
  558.  
  559.     while (error == 0) {
  560.         strcpy(fullname,p+30);
  561.         if(fullname[0] == '.') {               /* then a directory . or .. */
  562.             strcpy(files[*numfiles].name,fullname);
  563.             strcpy(files[*numfiles].extn,""); 
  564.         }
  565.         else {                                  /* a real file */
  566.  
  567.             dotat = FS_find_last_delim('.',fullname);
  568.             if (dotat == -1) { 
  569.                 strcpy(files[*numfiles].extn,"");
  570.                 strcpy(files[*numfiles].name,fullname);
  571.             }
  572.             else {
  573.                 strcpy(files[*numfiles].extn,&fullname[dotat+1]);
  574.                 strncpy(files[*numfiles].name,fullname,dotat);
  575.                 files[*numfiles].name[dotat] = '\0';
  576.             }
  577.         }
  578.         files[*numfiles].dirflag = (*(p+21) & 0x10) ? TRUE : FALSE ;
  579.         (*numfiles)++;                                /* count the discovered file */
  580.         if (*numfiles > MAXFILES-1) {                /* is this possible??? */
  581.             *numfiles = MAXFILES-1;                    /* if so, just ignore later files */
  582.             return(1);                                /* kinda sloppy huh ??? */
  583.         }
  584.         error = Fsnext();                            /* then look for another */
  585.     }
  586.     
  587.     /* now find all directories and put at beginning of list */
  588.     numdirs = 0;
  589.     for (i=0; i< *numfiles; i++) {
  590.         if(files[i].dirflag) {
  591.             FS_exchinfo(&files[numdirs],&files[i]); /* if dir, swap to beginning of list */
  592.             numdirs++;                                /* and count it */
  593.         }
  594.     }
  595.  
  596.     /* now sort the directories */
  597.     if ((numdirs) > 1) {
  598.         do {
  599.             exch = FALSE;
  600.             for(i=0; i<numdirs-1; i++) {            /* for all directories */
  601.                 if(strcmp(files[i].name,files[i+1].name) > 0) {
  602.                     FS_exchinfo(&files[i],&files[i+1]);
  603.                 }
  604.             }
  605.         } while (exch == TRUE);
  606.     }
  607.     
  608.     /* and now sort real files */
  609.     if ((*numfiles-numdirs) > 1) {
  610.         do {
  611.             exch = FALSE;
  612.             for(i=numdirs; i< *numfiles-1; i++) {    /* for all files */
  613.                 if(strcmp(files[i].name,files[i+1].name) > 0) {
  614.                     FS_exchinfo(&files[i],&files[i+1]);
  615.                     exch = TRUE;
  616.                 }
  617.             }
  618.         } while (exch == TRUE);
  619.     }            
  620.             
  621.     /* all done so return status */
  622.     if (error == -49) return (1) ;                   /* success if error = "no more files" */
  623.      return(0);                                         /* else a problem */
  624. }
  625.  
  626. /* 
  627.  * function FS_dir_select_good() scans files[] for files matching at least one of
  628.  * specified extensions.  Counts matches in numgood, stores index (into files[])
  629.  * in goodfiles[]. Also sets curfirst = 0 so later display will start at beginning.
  630.  */
  631. FS_dir_select_good(sextn,extn0,extn1,extn2,extn3,extn4,files,numfiles,goodfiles,numgood,curfirst)
  632. int          sextn;                                    /* the mask specifying checkable extensions */
  633. char         *extn0,*extn1,*extn2,*extn3,*extn4;    /* the extensions to try matching */
  634. struct finfo files[];
  635. int          numfiles,goodfiles[],*numgood,*curfirst;
  636.  
  637. {
  638. int i;
  639.     
  640.     *curfirst = 0;
  641.     *numgood  = 0;
  642.  
  643.     for (i=0; i<numfiles; i++) {                    /* always match directories */
  644.         if(files[i].dirflag) {
  645.             goodfiles[(*numgood)++] = i;
  646.             continue;
  647.         }
  648.         if((sextn & 0x01) && FS_wildmatch(extn0,files[i].extn)) {
  649.             goodfiles[(*numgood)++] = i;
  650.             continue;
  651.         }
  652.         if((sextn & 0x02) && FS_wildmatch(extn1,files[i].extn)) {
  653.             goodfiles[(*numgood)++] = i;
  654.             continue;
  655.         }
  656.         if((sextn & 0x04) && FS_wildmatch(extn2,files[i].extn)) {
  657.             goodfiles[(*numgood)++] = i;
  658.             continue;
  659.         }
  660.         if((sextn & 0x08) && FS_wildmatch(extn3,files[i].extn)) {
  661.             goodfiles[(*numgood)++] = i; 
  662.             continue;
  663.         }
  664.         if((sextn & 0x10) && FS_wildmatch(extn4,files[i].extn)) {
  665.             goodfiles[(*numgood)++] = i;
  666.             continue;
  667.         }
  668.     }
  669. }
  670.  
  671. /*
  672.  * function FS_dir_dis() displays current directory in window.  It displays
  673.  * at max WINDSIZE names, starting at 'curfirst' in files[].
  674.  */
  675. FS_dir_dis(files,goodfiles,numgood,curfirst)
  676. struct finfo files[];
  677. int          goodfiles[],numgood,curfirst;
  678. {
  679. int i,j;
  680.  
  681.     /* first, clear out display strings */
  682.     for (i=0; i<WINDSIZE; i++) {
  683.         for(j=0; j<16; j++)
  684.             file_ids[i][j] = ' ';
  685.         file_ids[i][16]    = '\0';
  686.     }
  687.     
  688.     /* now build  at most WINDSIZE filenames */
  689.     for (i=0,j=curfirst; i<WINDSIZE; i++,j++) {
  690.         if (j >= numgood) break;                                /* in case not enough good files to fill window */    
  691.         FS_strxcpy(&file_ids[i][2],files[goodfiles[j]].name);    /* put in basic filename */        
  692.         if (strlen(files[goodfiles[j]].extn) > 0) {                /* if there is an extension... */
  693.             file_ids[i][10] = '.';
  694.             FS_strxcpy(&file_ids[i][11],files[goodfiles[j]].extn);
  695.         }
  696.         if (files[goodfiles[j]].dirflag)
  697.             file_ids[i][0]  = DIAMOND_THINGY;                    /* put in funny box if its a directory */
  698.     }
  699.     
  700.     /* and finally 'print' all to screen */
  701.     for (i=0; i< WINDSIZE; i++) 
  702.         rs_object[FNAM1+i].ob_state = NORMAL;                    /* unselect all filenames */
  703.     objc_draw(&rs_object,FILEBOX,2,xdial,ydial,wdial,hdial);    /* blank the FILEBOX then write in all filenames */
  704.     FS_calc_slid_box(numgood,curfirst,1);                        /* redraw sliding box too */
  705.     objc_draw(&rs_object,TOPBAR, 0,xdial,ydial,wdial,hdial);    /* redraw TOPBAR to erase old path name */
  706.     objc_draw(&rs_object,TOPTEXT,0,xdial,ydial,wdial,hdial);    /* then redraw TOPTEXT  so that new path is shown */
  707. }
  708.     
  709. /* 
  710.  * function FS_path_lengthen() is called to add a newly
  711.  * selected name to the current pathlist.  It is assumed that
  712.  * the newly selected name is a directory...
  713.  */
  714. FS_path_lengthen(path,index,files,dispath)
  715. struct finfo files[];
  716. char *path,            /* the current path name (ends with '\') */
  717.      *dispath;        /* the truncated displayable version of same */
  718. int  index;            /* index into FS_files[] of name to add  */
  719. {
  720.     strcat(path,files[index].name);                /* add the name itself */
  721.     if (strlen(files[index].extn) > 0) {          /* (if there is an extension */
  722.         strcat(path,".");                        /* then append it */
  723.         strcat(path,files[index].extn);
  724.     }
  725.     strcat(path,"\\");                            /* and put on trailing backslash */
  726.     FS_pathtrunc(dispath,path);                    /* make displayable version */
  727. }
  728.  
  729. /* 
  730.  * function FS_path_shorten() shortens the current path. 
  731.  * It is called after click on ".."
  732.  * Note that the path must always start and end with a '\' 
  733.  * character (will always have a length of at least 1).
  734.  */
  735. FS_path_shorten(path,dispath)
  736. char *path,*dispath;
  737. {
  738. int len,i;
  739.     
  740.     len=strlen(path);
  741.     if (len == 1) return;                /* already minimum path */
  742.     i=len-2;                            /* points at char before trailing slash */
  743.     while(path[i] != '\\') i-- ;        /* keep looking for a slash */
  744.     path[i+1] = '\0' ;                    /* and put a terminator after it */
  745.     FS_pathtrunc(dispath,path);            /* make displayable version */
  746. }
  747.  
  748. /* 
  749.  * function pathtrunc() truncates real pathname into shorter displayable version
  750.  */
  751. FS_pathtrunc(dpath,spath)
  752. char *dpath,                            /* the output (destination) string */
  753.      *spath;                            /* the (maybe too long) source str */
  754. {
  755. int slen,i,is,id;
  756.  
  757.     if((slen=strlen(spath)) <= 16) strcpy(dpath,spath);    /* the trivial case */
  758.     else {
  759.         is = slen - 1 ;                    /* index of last char in string */
  760.         id = 15 ;                         /* last position in destination string */
  761.         for(i=0; i<14; i++)                /* copy 14 chars into 16 char field */
  762.             dpath[id--] = spath[is--];
  763.         dpath[0] = '<';                    /* and put little flags at beginning */
  764.         dpath[1] = '<';
  765.     }
  766. }
  767.  
  768. /* 
  769.  * function FS_wildmatch() checks a specified extension
  770.  * against a mask value for match, and returns TRUE if matched, else FALSE.
  771.  * Cases causing match are as follows:
  772.  *     exact match
  773.  *     mask value is "*"
  774.  *     match on all existing characters, with any '?' in mask matching anything
  775.  * Note that the mask value may have trailing spaces (" ") or underbars ("_") as
  776.  * a result of the object template process.  These are considered junk and are
  777.  * removed from the comparison process.
  778.  */
  779. FS_wildmatch(mask,candidate)
  780. char *mask,*candidate;
  781. {
  782. int masklen,i;
  783.  
  784.     if(mask[0]=='*') return(TRUE);                        /*  a '*' in mask matches anything */
  785.     
  786.     masklen = strlen(mask);                                /* will elim trailing spaces and underbars */
  787.     for(i=masklen-1; i>0; i--)                             /* check all but first char to see if it is ignorable */
  788.         if((mask[i]==' ') || (mask[i]=='_')) masklen=i;    /* adjust length word to effect ignorance */
  789.     if(strlen(candidate) > masklen) return(FALSE);      /* candidate .OLD should not match mask .O */
  790.         
  791.     for(i=0; i<masklen; i++) {                            /* now look at all valid chars to check for match */
  792.         if(mask[i] == '?') continue;                    /* a '?' in mask matches anything in that position */
  793.         if(toupper(mask[i]) != toupper(candidate[i])) return(FALSE);    /* oops -- no match */
  794.     }
  795.     
  796.     return(TRUE);                                        /* must have matched ! */
  797. }
  798.     
  799.     
  800.  
  801. /*
  802.  * function FS_exchinfo() exchanges contents of two 'finfo' style structures 
  803.  */        
  804. FS_exchinfo(x,y)
  805. struct finfo *x,*y;
  806. {
  807. struct finfo t;
  808.  
  809.      t = *x;    /* caution -- */
  810.     *x = *y;    /* this all-in-one assignment is an extension that works in MM C */
  811.     *y =  t;    /* other C's take care ... */
  812. }
  813.     
  814.  
  815. FS_find_last_delim(delim,string)
  816. char delim,*string;
  817. {
  818. int i,spot;
  819.  
  820.     spot = -1;
  821.     for (i=0; i<strlen(string); i++) 
  822.         if (string[i] == delim) spot = i;
  823.     return(spot);
  824. }
  825.  
  826. /*
  827.  * function FS_strxcpy() is just like strcpy except it does not copy 
  828.  * the terminating \0
  829.  */
  830. FS_strxcpy(dest,sour)
  831. char *dest,*sour;
  832. {
  833. char c;
  834.     while ((c=*sour++) != '\0') *dest++ = c ;
  835. }
  836.  
  837.